package controller

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/e421083458/gorm"
	"github.com/gin-gonic/gin"
	"github.com/go-redis/redis"
	"github.com/gogf/gf/util/gconv"
	"github.com/medivhzhan/weapp/v2"
	"io/ioutil"
	"net/http"
	"rock/customer/dto"
	"rock/customer/initParam"
	"rock/customer/middleware"
	"rock/customer/models"
	"rock/customer/modules/cacheMap"
	"rock/customer/modules/redisModules"
	"rock/customer/public"
	"time"
)

// @Summary 微信登录认证
// @Description 传参只需要传JsCode，Type。https://api.weixin.qq.com/sns/jscode2session?appid=xxxc&secret=xxx&js_code=xxx&grant_type=authorization_code
// @Tags 微信
// @ID   /wechatlogin
// @Accept  json
// @Produce  json
// @Param polygon body dto.WeChatLogin true "body"
// @Success 200 {object} middleware.Response{data=dto.WechatLoginOutput} "success"
// @Router /wechatlogin [post]
func (a *AuthenticationController) wechatLogin(router *gin.Context) {
	params := &dto.WeChatLogin{}
	if err := params.BindingParams(router); err != nil {
		middleware.ResponseError(router, middleware.PARMAS_ERROR_CODE, err)
		return
	}
	if *params.Type != 1 && *params.Type != 2 {
		middleware.ResponseError(router, middleware.PARMAS_ERROR_CODE, errors.New("type value error"))
		return
	}
	appid := initParam.WeChatFAEConf.AppId
	secret := initParam.WeChatFAEConf.Secret
	grantType := initParam.WeChatFAEConf.GrantType
	if *params.Type == 2 {
		appid = initParam.WeChatClientConf.AppId
		secret = initParam.WeChatClientConf.Secret
		grantType = initParam.WeChatClientConf.GrantType
	}
	urls := fmt.Sprintf(`https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=%s`, appid, secret, params.JsCode, grantType)
	resp, err := http.Get(urls)
	if err != nil {
		middleware.ResponseError(router, middleware.INTERNAL_ERROR_CODE, err)
		return
	}
	bytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		middleware.ResponseError(router, middleware.INTERNAL_ERROR_CODE, err)
		return
	}
	reData := &dto.WechatLoginOutput{}
	err = json.Unmarshal(bytes, reData)
	if err != nil {
		middleware.ResponseError(router, middleware.INTERNAL_ERROR_CODE, err)
		return
	}
	if reData.Errcode != 0 {
		errMsg := reData.Errmsg
		if reData.Errcode == 40029 {
			errMsg = initParam.WeChatErrText40029
		} else if reData.Errcode == 45011 {
			errMsg = initParam.WeChatErrText45011
		} else if reData.Errcode == -1 {
			errMsg = initParam.WeChatErrText1
		}
		middleware.ResponseError(router, middleware.INTERNAL_ERROR_CODE, errors.New(errMsg))
		return
	}
	imUser := redisModules.ImUser{
		MiniProgramAppId: appid,
		UnionId:          reData.Unionid,
		Openid:           reData.Openid,
	}
	v, err := json.Marshal(imUser)
	if err != nil {
		middleware.ResponseError(router, middleware.INTERNAL_ERROR_CODE, err)
		return
	} else {
		if params.IsCustomerClient == 1 {
			redisModules.ClientRedis.Set("ClientApp_"+reData.Unionid, string(v), 72*time.Hour)
		} else {
			redisModules.ClientRedis.Set("FaeApp_"+reData.Unionid, string(v), 72*time.Hour)
		}
	}
	responseData := reData
	middleware.ResponseSuccess(router, responseData)
}

// @Summary 获取微信手机号码
// @Description 传参只需要传Sessionkey，EncryptedData，Iv
// @Tags 微信
// @ID   /getwechatmobile
// @Accept  json
// @Produce  json
// @Param polygon body dto.GetWechatMobileInput true "body"
// @Success 200 {object} middleware.Response{data=dto.GetWechatMobileOutput} "success"
// @Router /getwechatmobile [post]
func (a *AuthenticationController) getWechatMobile(router *gin.Context) {
	params := &dto.GetWechatMobileInput{}
	if err := params.BindingParams(router); err != nil {
		middleware.ResponseError(router, middleware.PARMAS_ERROR_CODE, err)
		return
	}
	res, err := weapp.DecryptMobile(params.Sessionkey, params.EncryptedData, params.Iv)
	if err != nil {
		middleware.ResponseError(router, middleware.INTERNAL_ERROR_CODE, err)
		return
	}
	responseData := *res
	middleware.ResponseSuccess(router, responseData)
}

// @Summary 发送公众号通知消息
// @Description
// @Tags 微信
// @ID   /sendnoticemsg
// @Accept  json
// @Produce  json
// @Param polygon body dto.User true "body"
// @Success 200 {object} middleware.Response{} "success"
// @Router /sendnoticemsg [post]
func (a *AuthenticationController) sendNoticeMsg(router *gin.Context) {
	params := &dto.User{}
	if err := params.BindingParams(router); err != nil {
		middleware.ResponseError(router, middleware.PARMAS_ERROR_CODE, err)
		return
	}
	if params.IsCustomerClient == 1 {

	} else {
		groupMemberC, err := groupService.GroupMemberC(router, BusinessDB, params.GroupId)
		if err != nil {
			dealRequestError(router, err)
			return
		}
		CustomerOnlineCache := cacheMap.CustomerOnline.Get(gconv.String(groupMemberC.UserID))
		if CustomerOnlineCache == nil {
			cacheMap.CustomerOnline.Set(gconv.String(groupMemberC.UserID), initParam.COnlineState)
			CustomerOnlineCache = cacheMap.CustomerOnline.Get(gconv.String(groupMemberC.UserID))
		}
		if CustomerOnlineCache.(int) == 1 {
			middleware.ResponseSuccess(router, gin.H{"msg": initParam.DealSuccessText})
			return
		}
		userDetail, err := userService.UserByUserId(router, InstanceDB, gconv.String(groupMemberC.UserID))
		if err != nil {
			middleware.ResponseError(router, middleware.INTERNAL_ERROR_CODE, err)
			return
		}
		if userDetail.OpenId == "" {
			imUser := redisModules.RedisMiniAppUser("ClientApp_"+userDetail.UnionId, redisModules.ImUser{})
			if imUser.UnionId == "" {
				public.ContextNotice(router, "error", map[string]interface{}{
					"title": "sendNoticeMsg",
					"error": "imUser redis is not exist",
				})
				sendMsg("13530432646", initParam.ProductName, "431515")
				return
			}
			err = sendMiniProgramMsg(params.IsCustomerClient, imUser.Openid)
			if err != nil {
				middleware.ResponseError(router, middleware.INTERNAL_ERROR_CODE, err)
				return
			}
		} else {
			err = sendOfficialAccountMsg(params.IsCustomerClient, userDetail.OpenId, 1)
			if err != nil {
				middleware.ResponseError(router, middleware.INTERNAL_ERROR_CODE, err)
				return
			}
		}
	}
	middleware.ResponseSuccess(router, gin.H{"msg": initParam.DealSuccessText})
}

// @Summary 生成小程序url链接
// @Description
// @Tags 微信
// @ID   /generateurllink
// @Accept  json
// @Produce  json
// @Param polygon body dto.WechatLoginInput true "body"
// @Success 200 {object} middleware.Response{data=dto.Config} "success"
// @Router /generateurllink [post]
func (a *AuthenticationController) generateUrlLink(router *gin.Context) {
	params := &dto.WechatLoginInput{}
	if err := params.BindingParams(router); err != nil {
		middleware.ResponseError(router, middleware.PARMAS_ERROR_CODE, err)
		return
	}
	redisCache := redisModules.ClientRedis.Get(initParam.UrlLinkPrefix + params.Path + "_" + params.Query + "_" + gconv.String(params.IsCustomerClient))
	val, err := redisCache.Result()
	redisData := dto.Config{}
	if err == nil {
		err = json.Unmarshal([]byte(val), &redisData)
		if err != nil {
			fmt.Println(fmt.Sprintf("err => %v", err))
			return
		}
		responseData := redisData
		middleware.ResponseSuccess(router, responseData)
		return
	} else {
		if err != redis.Nil {
			middleware.ResponseError(router, middleware.INTERNAL_ERROR_CODE, err)
			return
		}
	}
	//key = isCustomerClient_$isCustomerClientpath_$pathquery_$query
	redisData, err = serviceService.Config(router, InstanceDB, initParam.UrlLinkPrefix+params.Path+"_"+params.Query+"_"+gconv.String(params.IsCustomerClient))
	if err != nil {
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			middleware.ResponseError(router, middleware.INTERNAL_ERROR_CODE, err)
			return
		}
		weChatData := &dto.WechatLoginOutput{}
		err = generateUrlLink(router, params.IsCustomerClient, params.Path, params.Query, weChatData)
		if err != nil {
			middleware.ResponseError(router, middleware.INTERNAL_ERROR_CODE, err)
			return
		}
		if weChatData.UrlLink == "" {
			middleware.ResponseError(router, middleware.INTERNAL_ERROR_CODE, err)
			return
		}
		err = serviceService.CreateConfig(router, BusinessDB, &models.WkbImConfig{
			Key:   initParam.UrlLinkPrefix + params.Path + "_" + params.Query + "_" + gconv.String(params.IsCustomerClient),
			Value: weChatData.UrlLink,
		})
		if err != nil {
			middleware.ResponseError(router, middleware.INTERNAL_ERROR_CODE, err)
			return
		}
		redisData.Key = initParam.UrlLinkPrefix + params.Path + "_" + params.Query + "_" + gconv.String(params.IsCustomerClient)
		redisData.Value = weChatData.UrlLink
	}
	err = addRedis(router, redisData, initParam.UrlLinkPrefix+params.Path+"_"+params.Query+"_"+gconv.String(params.IsCustomerClient))
	if err != nil {
		middleware.ResponseError(router, middleware.INTERNAL_ERROR_CODE, err)
		return
	}
	responseData := redisData
	middleware.ResponseSuccess(router, responseData)
}

// @Summary pc微信登录
// @Description
// @Tags 微信
// @ID   /wechatloginqrcode
// @Accept  json
// @Produce  json
// @Param polygon body dto.WeChatLogin true "body"
// @Success 200 {object} middleware.Response{} "success"
// @Router /wechatloginqrcode [post]
func (a *AuthenticationController) weChatLoginQrCode(router *gin.Context) {
	params := &dto.WeChatLogin{}
	if err := params.BindingParams(router); err != nil {
		middleware.ResponseError(router, middleware.PARMAS_ERROR_CODE, err)
		return
	}
	qrCode := weChatLoginQrCode()
	if qrCode == "" {
		middleware.ResponseError(router, middleware.INTERNAL_ERROR_CODE, nil)
		return
	}
	middleware.ResponseSuccess(router, gin.H{
		"qrCode": qrCode,
	})
}
